package FileControl.Source;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Observer;

import FileControl.FileControl;

public class CopyThread extends KillableThread implements Observable{
	
	private File source,dest;
	private boolean result;
	private long totalSize;
	public long sizeCompleted;
	private long sizeRemaining;
	private Date start,stop;
	
	public static boolean debug = false;
	
	private static List<Observer> toNotify;

	public CopyThread(File source, File dest) {
		this.source = source;
		this.dest = dest;
		totalSize = source.length();
		sizeCompleted = 0;
		sizeRemaining = totalSize;
		toNotify = new LinkedList<Observer>();
		println("CopyThread created: \n \t size: " + totalSize + " \n \t source: " + source.getAbsolutePath() + "\n \t dest: " + dest.getAbsolutePath());
	}
	
	public void run() {
		start = new Date();
		this.hasStarted = true;
		result = this.basicCopy(source,dest);
		println("CopyThread complete: \n \t source: " + source.getAbsolutePath() + "\n \t dest: " + dest.getAbsolutePath());
		this.finished = true;
		stop = new Date();
	}
	
	public boolean basicCopy(File source, File dest) {
		boolean success = true;
		FileInputStream in = null;
		FileOutputStream out = null;
		try {
			in = new FileInputStream(source);
			out = new FileOutputStream(dest);
		    
			 // Transfer bytes from in to out
			 byte[] buf = new byte[CopyFile.bufSize];
			 int len;
			 while ((len = in.read(buf)) > 0) {
				 this.sizeCompleted = this.sizeCompleted + len;
				 out.write(buf, 0, len);
				 notifyObservers();
			 }
		} catch (FileNotFoundException e) {e.printStackTrace(); success = false;
		} catch (IOException e) {e.printStackTrace(); success = false;
		} finally {
			 if(in != null) {
				 try {
					in.close();
				} catch (IOException e) {e.printStackTrace();}
			 }
			 if(out != null) {
				 try {
					out.close();
				 } catch (IOException e) {e.printStackTrace();}
			 }
		}
		return success;
	}
	
	public boolean copyDestCheck(File source, File dest) {
		if(dest.exists()) {
			println(source.getName() + ": FILE ALREADY EXISTS!");
			return false;
		} else {
			return basicCopy(source, dest);
		}
	}
	
	public boolean getResult() {
		return result;
	}
	
	public File getSource() {
		return source;
	}
	
	public long bytesCompleted() {
		return sizeCompleted;
	}
	
	public long size() {
		return totalSize;
	}
	
	public double getPercentDone() {
		return ((double)((int)((((double)sizeCompleted) / ((double)totalSize)) * 10000)))/100;
	}
	
	public long getStartTime() {
		return start.getTime();
	}
	
	public long getRunTime() {
		return stop.getTime() - start.getTime();
	}
	
	public double getTimeAvg() {
		return (double)getRunTime() / (double)source.length();
	}

	public void addObserver(Observer o) {
		toNotify.add(o);
	}
	
	public static void notifyObservers() {
		for(Observer o : toNotify) {
			o.notify();
		}
	}
	
	public void println(Object o) {
		if(debug)
			System.out.println(o);
	}
}
